package com.yanqu.road.server.cmd.activity.uniongroup;

import com.yanqu.road.entity.union.activitygroup.UnionActivityGroup;
import com.yanqu.road.entity.union.activitygroup.UnionActivityGroupUnion;
import com.yanqu.road.entity.union.activitygroup.UnionActivityGroupUser;
import com.yanqu.road.logic.pb.UnionActivityGroupPb;
import com.yanqu.road.message.YanQuMessage;
import com.yanqu.road.pb.union.UnionActivityGroupProto;
import com.yanqu.road.server.GameServer;
import com.yanqu.road.server.command.Cmd;
import com.yanqu.road.server.command.Command;
import com.yanqu.road.server.gameplayer.GamePlayer;
import com.yanqu.road.server.gameplayer.module.player.UnionActivityGroupModule;
import com.yanqu.road.server.manger.player.GamePlayerMgr;
import com.yanqu.road.server.manger.union.GameUnionActivityGroupMgr;
import com.yanqu.road.server.protocol.CrossProtocol;
import com.yanqu.road.server.protocol.Protocol;
import com.yanqu.road.utils.YanQuMessageUtils;
import io.netty.channel.ChannelHandlerContext;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;

@Cmd(code = Protocol.S_UNION_ACTIVITY_GROUP_SYNC, desc = "商会活动分组名单同步")
public class UnionActivityGroupSyncCmd implements Command {

    @Override
    public void execute(ChannelHandlerContext ctx, YanQuMessage yanQuMessage) throws Exception {
        UnionActivityGroupProto.UnionActivityGroupSyncReqMsg syncMsg = UnionActivityGroupProto.UnionActivityGroupSyncReqMsg.parseFrom(yanQuMessage.getBytes());

        // 【全量数据处理】
        if (syncMsg.getAllGroupCount() > 0) {
            Map<Integer, Map<Integer, UnionActivityGroup>> mapMap = new ConcurrentHashMap<>();
            for (UnionActivityGroupProto.UnionActivityGroupMsg groupMsg : syncMsg.getAllGroupList()) {
                if (!groupMsg.getServerIdList().contains(GameServer.getInstance().getServerId())) {
                    continue; // 去掉不需要的数据
                }
                UnionActivityGroup group = UnionActivityGroupPb.parseUnionActivityGroup(groupMsg);
                mapMap.putIfAbsent(group.getActivityId(), new ConcurrentHashMap<>());
                mapMap.get(group.getActivityId()).put(group.getGroupId(), group);
            }

            for (Map.Entry<Integer, Map<Integer, UnionActivityGroup>> entry : mapMap.entrySet()) {
                int activityId = entry.getKey();
                Map<Integer, UnionActivityGroup> groupMap = entry.getValue();
                List<Long> changeList = checkChangeAbleUser(activityId, groupMap); // 拿出新获得资格的玩家
                GameUnionActivityGroupMgr.putGroupMap(activityId, groupMap); // 数据添加
                syncAble(activityId, changeList); // 同步新获得资格的玩家

                // 【原路返回确认】
                UnionActivityGroupProto.UnionActivityGroupSyncRespMsg.Builder builder = UnionActivityGroupProto.UnionActivityGroupSyncRespMsg.newBuilder();
                builder.setActivityId(activityId);
                builder.setServerId(GameServer.getInstance().getServerId());
                YanQuMessage message = YanQuMessageUtils.buildMessage(CrossProtocol.C_UNION_ACTIVITY_GROUP_SYNC_RESP, builder);
                GamePlayerMgr.sendPacket(0, message);
            }
        }

        // 【增量数据处理】
        if (syncMsg.getUpdateUnionCount() > 0) {
            for (UnionActivityGroupProto.UnionActivityGroupUnionUpdateMsg unionUpdateMsg : syncMsg.getUpdateUnionList()) {
                UnionActivityGroupUnion union = UnionActivityGroupPb.parseUnionActivityGroupUnion(unionUpdateMsg);
                List<Long> changeList = checkChangeAbleUser(union); // 拿出新获得资格的玩家
                GameUnionActivityGroupMgr.updateGroupUnion(union); // 数据添加
                syncAble(union.getActivityId(), changeList); // 同步新获得资格的玩家
            }
        }
    }

    private List<Long> checkChangeAbleUser(int activityId, Map<Integer, UnionActivityGroup> groupMap) {

        long serverId = GameServer.getInstance().getServerId();

        Set<Long> oldSet = new HashSet<>();
        Map<Integer, UnionActivityGroup> oldMap = GameUnionActivityGroupMgr.getGroupMap(activityId);
        if (oldMap != null) {
            for (UnionActivityGroup group : oldMap.values()) {
                for (UnionActivityGroupUnion union : group.getUnionDataMap().values()) {
                    for (UnionActivityGroupUser user : union.getUserMap().values()) {
                        if (user.getServerId() == serverId) {
                            oldSet.add(user.getUserId());
                        }
                    }
                }
            }
        }

        Set<Long> newSet = new HashSet<>();
        for (UnionActivityGroup group : groupMap.values()) {
            for (UnionActivityGroupUnion union : group.getUnionDataMap().values()) {
                for (UnionActivityGroupUser user : union.getUserMap().values()) {
                    if (user.getServerId() == serverId) {
                        newSet.add(user.getUserId());
                    }
                }
            }
        }

        List<Long> changeList = new ArrayList<>();
        for (long userId : newSet) {
            if (!oldSet.contains(userId)) {
                changeList.add(userId);
            }
        }
        return changeList;
    }

    private List<Long> checkChangeAbleUser(UnionActivityGroupUnion newUnion) {
        UnionActivityGroupUnion oldUnion = GameUnionActivityGroupMgr.getUnionData(newUnion.getActivityId(), newUnion.getUnionUid());

        long serverId = GameServer.getInstance().getServerId();

        Set<Long> oldSet = new HashSet<>();
        if (oldUnion != null) {
            for (UnionActivityGroupUser user : oldUnion.getUserMap().values()) {
                if (user.getServerId() == serverId) {
                    oldSet.add(serverId);
                }
            }
        }

        Set<Long> newSet = new HashSet<>();
        for (UnionActivityGroupUser user : newUnion.getUserMap().values()) {
            if (user.getServerId() == serverId) {
                newSet.add(user.getUserId());
            }
        }

        List<Long> changeList = new ArrayList<>();
        for (long userId : newSet) {
            if (!oldSet.contains(userId)) {
                changeList.add(userId);
            }
        }
        return changeList;
    }

    private void syncAble(int activityId, List<Long> userList) {
        for (long userId : userList) {
            GamePlayer onlinePlayer = GamePlayerMgr.getOnlinePlayer(userId);
            if (onlinePlayer != null) {
                // onlinePlayer.getModule(UnionActivityGroupModule.class).syncOneAble(activityId, true); // 客户端没处理增量
                onlinePlayer.getModule(UnionActivityGroupModule.class).syncAble(); // 全量同步玩家资格（反正数据很少）
            }
        }
    }

}
